﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CS_BEGINNER_TO_PROFICIENT.STD.DelegatedSTD
{
    public delegate void CallRecivedHandler<T>(T callDetails);

    public class CallDetails : EventArgs
    { 
        public string CallerName { get; }
        public string PhoneNumber { get; }

        public CallDetails(string callerName, string phoneNumber)
        {
            CallerName = callerName;
            PhoneNumber = phoneNumber;
        }

        public override string ToString() => $"Caller: {CallerName}, Phone: {PhoneNumber}";
    }

    public class InComingCall<T>
    {
        public event CallRecivedHandler<T> CallReceived;
        private readonly T _callDetails;

        public InComingCall(T callDetails) => _callDetails = callDetails;


        public void Receice() => OnCallReceived(_callDetails);

        protected virtual void OnCallReceived(T callDetails) => CallReceived?.Invoke(callDetails);
    }

    public class NotificationSystem
    {
        private readonly List<InComingCall<CallDetails>> _calls = new List<InComingCall<CallDetails>>();

        public void Regiter(InComingCall<CallDetails> call, CallRecivedHandler<CallDetails> handler)
        {
            // small task
            Action<InComingCall<CallDetails>, CallRecivedHandler<CallDetails>> action = (t, u) =>
            {
                t.CallReceived += handler;
                _calls.Add(t);
            };

            action(call, handler);
        }

        public void Unregister(InComingCall<CallDetails> call, CallRecivedHandler<CallDetails> handler)
        {
            Action<InComingCall<CallDetails>, CallRecivedHandler<CallDetails>> action = (t, u) =>
            {
                t.CallReceived -= handler;
                _calls.Remove(t);
            };

            action(call, handler);
        }
    }

    public class CallHandler
    {
        public void HandleCallReceived(CallDetails callDetails) 
            => Console.WriteLine($"Notification: Received call from {callDetails.CallerName} at {callDetails.PhoneNumber}");
    }

    public class DelegatedSTDP17
    {
        public static void Execute()
        {
            InComingCall<CallDetails> comingCall1 = new InComingCall<CallDetails>(new CallDetails("fzy", "133"));
            InComingCall<CallDetails> comingCall2 = new InComingCall<CallDetails>(new CallDetails("lx", "177"));

            NotificationSystem notificationSystem = new NotificationSystem();
            CallHandler callHandler = new CallHandler();

            notificationSystem.Regiter(comingCall1, callHandler.HandleCallReceived);
            notificationSystem.Regiter(comingCall2, callHandler.HandleCallReceived);

            comingCall1.Receice();
            comingCall2.Receice();
        }
    }
}
